/**
 * updated 20100921
 */
package cc.mango.android.chart;

import java.util.ArrayList;
import java.util.List;

import org.achartengine.chart.ScatterChart;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries;
import org.achartengine.renderer.SimpleSeriesRenderer;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYMultipleSeriesRenderer.Orientation;
import org.achartengine.util.MathHelper;

import cc.mango.common.FinalKey;

import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.Paint.Align;
import android.graphics.Paint.Style;

/**
 * The bar chart rendering class.
 */
public class DownBarChart extends DownXYChart
{
	/** The legend shape width. */
	private static final int	SHAPE_WIDTH		= 12;
	/** The chart type. */
	protected Type			mType			= Type.DEFAULT;

	///////////////by zhengan

	private float			lineStrokeWidth	= 2;

	/**
	 * The bar chart type enum.
	 */
	public enum Type
	{
		DEFAULT, STACKED, LINE;
	}

	/**
	 * Builds a new bar chart instance.
	 * 
	 * @param dataset the multiple series dataset
	 * @param renderer the multiple series renderer
	 * @param type the bar chart type
	 */
	public DownBarChart(XYMultipleSeriesDataset dataset,
			XYMultipleSeriesRenderer renderer, Type type)
	{
		super(dataset, renderer);
		mType = type;
	}

	/**
	 * The graphical representation of the XY chart.
	 * 
	 * @param canvas the canvas to paint to
	 * @param x the top left x value of the view to draw to
	 * @param y the top left y value of the view to draw to
	 * @param width the width of the view to draw to
	 * @param height the height of the view to draw to
	 */
	@Override
	public void draw(Canvas canvas, int x, int y, int width, int height)
	{
		Paint paint = new Paint();
		paint.setAntiAlias(mRenderer.isAntialiasing());

		initSize(width, height);

		int left = x + leftWidth;
		int top = y + topHeight;
		int right = x + width - rightWidth;
		int bottom = y + height - bottomHeight;
		if (screenR == null)
		{
			screenR = new Rect();
		}
		screenR.set(left, top, right, bottom);

		//    drawBackground(mRenderer, canvas, x, y, width, height, paint);
		///by zha//////////////
		drawBackground(mRenderer, canvas, left, top - 2, right - left, bottom
				- top + 2, paint);
		//by zhengan////////////

		if (paint.getTypeface() == null
				|| !paint.getTypeface().toString().equals(
						mRenderer.getTextTypefaceName())
				|| paint.getTypeface().getStyle() != mRenderer
						.getTextTypefaceStyle())
		{
			paint.setTypeface(Typeface.create(mRenderer
					.getTextTypefaceName(), mRenderer
					.getTextTypefaceStyle()));
		}
		Orientation or = mRenderer.getOrientation();

		double minX = mRenderer.getXAxisMin();
		double maxX = mRenderer.getXAxisMax();
		double minY = mRenderer.getYAxisMin();
		double maxY = mRenderer.getYAxisMax();
		boolean isMinXSet = mRenderer.isMinXSet();
		boolean isMaxXSet = mRenderer.isMaxXSet();
		boolean isMinYSet = mRenderer.isMinYSet();
		boolean isMaxYSet = mRenderer.isMaxYSet();
		//by zhengan
		//    double xPixelsPerUnit = 0;
		//    double yPixelsPerUnit = 0;    
		/////by zhengan  

		int sLength = mDataset.getSeriesCount();
		String[] titles = new String[sLength];
		for (int i = 0; i < sLength; i++)
		{
			XYSeries series = mDataset.getSeriesAt(i);
			titles[i] = series.getTitle();
			if (series.getItemCount() == 0)
			{
				continue;
			}
			if (!isMinXSet)
			{
				double minimumX = series.getMinX();
				minX = Math.min(minX, minimumX);
				calcRange[0] = minX;
			}
			if (!isMaxXSet)
			{
				double maximumX = series.getMaxX();
				maxX = Math.max(maxX, maximumX);
				calcRange[1] = maxX;
			}
			if (!isMinYSet)
			{
				double minimumY = series.getMinY();
				minY = Math.min(minY, (float) minimumY);
				calcRange[2] = minY;
			}
			if (!isMaxYSet)
			{
				double maximumY = series.getMaxY();
				maxY = Math.max(maxY, (float) maximumY);
				calcRange[3] = maxY;
			}
		}
		if (maxX - minX != 0)
		{
			//      xPixelsPerUnit = (right - left) / (maxX - minX);
			int count = this.mDataset.getSeriesAt(0).getItemCount();
			if (count == 0)
			{
				return;
			}
			xPixelsPerUnit = 1.0f * (right - left) / (count - 1);
		}
		if (maxY - minY != 0)
		{
			yPixelsPerUnit = (float) ((bottom - top) / (maxY - minY));

			//    	yPixelsPerUnit = 1 ((bottom - top) / (maxY - minY));
		}

		if (getIsTouching())
		{
			drawVerticalLine(canvas, getXLocation(getIndex()), top, bottom);

		}

		boolean hasValues = false;
		for (int i = 0; i < sLength; i++)
		{
			XYSeries series = mDataset.getSeriesAt(i);
			if (series.getItemCount() == 0)
			{
				continue;
			}
			hasValues = true;
			SimpleSeriesRenderer seriesRenderer = mRenderer
					.getSeriesRendererAt(i);
			int originalValuesLength = series.getItemCount();
			float[] points = null;
			int valuesLength = originalValuesLength;
			int length = valuesLength * 2;
			points = new float[length];

			for (int j = 0; j < length; j += 2)
			{
				int index = j / 2;
				points[j] = (float) (left + xPixelsPerUnit * index);
				//	        points[j + 1] = (float) (bottom - yPixelsPerUnit * (series.getY(index) - minY));  //by zhengan
				points[j + 1] = (float) (bottom - yPixelsPerUnit
						* (series.getY(index) - minY) - 2);
			}

			/*   //当最下值不是0时，最小值会与X坐标重合，给用户没有成交量的感觉
			   if(minY > 0){
			 	  for (int j = 0; j < length; j += 2) {
			 	        int index = j / 2;
			 	        points[j] = (float) (left + xPixelsPerUnit * index);
			//    	        points[j + 1] = (float) (bottom - yPixelsPerUnit * (series.getY(index) - minY));  //by zhengan
			 	        points[j + 1] = (float) (bottom - yPixelsPerUnit * (series.getY(index) - minY) - 2);
			 	      }
			   }else{
			 	  
			 	  for (int j = 0; j < length; j += 2) {
			        int index = j / 2;
			        points[j] = (float) (left + xPixelsPerUnit * index);
			        points[j + 1] = (float) (bottom - yPixelsPerUnit * (series.getY(index) - minY));  //orign  

			      }
			 	  
			   }*/

			drawSeries(canvas, paint, points, seriesRenderer, Math.min(
					bottom, (float) (bottom + yPixelsPerUnit * minY)), i);

			if (isRenderPoints(seriesRenderer))
			{
				ScatterChart pointsChart = new ScatterChart(mDataset,
						mRenderer);
				pointsChart.drawSeries(canvas, paint, points,
						seriesRenderer, 0, i);
			}
			paint.setTextSize(mRenderer.getChartValuesTextSize());
			if (or == Orientation.HORIZONTAL)
			{
				paint.setTextAlign(Align.CENTER);
			}
			else
			{
				paint.setTextAlign(Align.LEFT);
			}
			if (mRenderer.isDisplayChartValues())
			{
				drawChartValuesText(canvas, series, paint, points, i);
			}
		}

		boolean showLabels = mRenderer.isShowLabels() && hasValues;

		if (showLabels)
		{
			paint.setColor(mRenderer.getLabelsColor());
			paint.setTextSize(mRenderer.getLabelsTextSize());
			paint.setTextAlign(Align.CENTER);

			//draw y labels
			drawYLabels(canvas, paint);

		}

	}

	/**
	   * The graphical representation of a series.
	   * 
	   * @param canvas the canvas to paint to
	   * @param paint the paint to be used for drawing
	   * @param points the array of points to be used for drawing the series
	   * @param seriesRenderer the series renderer
	   * @param yAxisValue the minimum value of the y axis
	   * @param seriesIndex the index of the series currently being drawn
	   */
	public void drawSeries(Canvas canvas, Paint paint, float[] points,
			SimpleSeriesRenderer seriesRenderer, float yAxisValue,
			int seriesIndex)
	{
		int seriesNr = mDataset.getSeriesCount();
		int length = points.length;
		paint.setColor(seriesRenderer.getColor());
		paint.setStyle(Style.FILL);
		float halfDiffX = 0;
		if (mType != Type.LINE)
			halfDiffX = getHalfDiffX(points, length, seriesNr);

		for (int i = 0; i < length; i += 2)
		{
			float x = points[i];
			float y = points[i + 1];
			if (mType == Type.LINE)
			{
				paint.setStrokeWidth(lineStrokeWidth);
				canvas.drawLine(x, yAxisValue, x, y, paint);
			}
			else if (mType == Type.STACKED)
			{
				canvas.drawRect(x - halfDiffX, y, x + halfDiffX,
						yAxisValue, paint);
			}
			else
			{
				float startX = x - seriesNr * halfDiffX + seriesIndex * 2
						* halfDiffX;
				canvas.drawRect(startX, y, startX + 2 * halfDiffX,
						yAxisValue, paint);
			}
		}
	}

	/**
	 * The graphical representation of the series values as text.
	 * 
	 * @param canvas the canvas to paint to
	 * @param series the series to be painted
	 * @param paint the paint to be used for drawing
	 * @param points the array of points to be used for drawing the series
	 * @param seriesIndex the index of the series currently being drawn
	 */
	protected void drawChartValuesText(Canvas canvas, XYSeries series,
			Paint paint, float[] points, int seriesIndex)
	{
		int seriesNr = mDataset.getSeriesCount();
		float halfDiffX = getHalfDiffX(points, points.length, seriesNr);
		for (int k = 0; k < points.length; k += 2)
		{
			float x = points[k];
			if (mType == Type.DEFAULT)
			{
				x += seriesIndex * 2 * halfDiffX - (seriesNr - 1.5f)
						* halfDiffX;
			}
			//      drawText(canvas, getLabel(series.getY(k / 2)), x, points[k + 1] - 3.5f, paint, 0);
		}
	}

	/**
	 * Returns the legend shape width.
	 * 
	 * @return the legend shape width
	 */
	public int getLegendShapeWidth()
	{
		return SHAPE_WIDTH;
	}

	/**
	 * The graphical representation of the legend shape.
	 * 
	 * @param canvas the canvas to paint to
	 * @param renderer the series renderer
	 * @param x the x value of the point the shape should be drawn at
	 * @param y the y value of the point the shape should be drawn at
	 * @param paint the paint to be used for drawing
	 */
	public void drawLegendShape(Canvas canvas, SimpleSeriesRenderer renderer,
			float x, float y, Paint paint)
	{
		float halfShapeWidth = SHAPE_WIDTH / 2;
		canvas.drawRect(x, y - halfShapeWidth, x + SHAPE_WIDTH, y
				+ halfShapeWidth, paint);
	}

	/**
	 * Calculates and returns the half-distance in the graphical representation of 2 consecutive points.
	 * @param points the points
	 * @param length the points length
	 * @param seriesNr the series number
	 * @return the calculated half-distance value
	 */
	protected float getHalfDiffX(float[] points, int length, int seriesNr)
	{
		float halfDiffX = (points[length - 2] - points[0]) / length;
		if (halfDiffX == 0)
		{
			halfDiffX = 10;
		}

		if (mType != Type.STACKED)
		{
			halfDiffX /= seriesNr;
		}
		return halfDiffX / getCoeficient();
	}

	/**
	 * Returns the value of a constant used to calculate the half-distance.
	 * @return the constant value
	 */
	protected float getCoeficient()
	{
		return 1;
	}

	public float getLineStrokeWidth()
	{
		return lineStrokeWidth;
	}

	public void setLineStrokeWidth(float lineStrokeWidth)
	{
		this.lineStrokeWidth = lineStrokeWidth;
	}

	@Override
	public boolean isRenderPoints(SimpleSeriesRenderer renderer)
	{
		// TODO Auto-generated method stub
		return false;
	}

}
